package S3;
use strict;
use warnings FATAL => qw(all);

use Apache2::Const -compile => qw(OK DECLINED);
use Apache2::RequestRec;
use APR::Table;
use MIME::Base64;
use Digest::SHA1;
use Digest::HMAC;
use POSIX;

sub _signature
{
    my ($key, $secret, $data) = @_;
    return "AWS $key:".MIME::Base64::encode_base64(Digest::HMAC::hmac($data, $secret, \&Digest::SHA1::sha1), "");
}

sub handler
{
    my $r = shift;
    my $h = $r->headers_in;
    my $uri = $r->uri;

    my %map = split /\s*(?:,|=>)\s*/, $r->dir_config("S3Map");

    foreach my $base (sort { length $b <=> length $a } keys %map)
    {
	$uri =~ s|^$base/*|| or next;

	my ($bucket, $keyId, $keySecret) = split m|/|, $map{$base};
	$keyId ||= $r->dir_config("S3Key");
	$keySecret ||= $r->dir_config("S3Secret");

	my $path = "/$bucket/$uri";
	my $date = POSIX::strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime);

	my $toSign = join "\n",
	    "GET",  # method
	    "",     # content-md5
	    "",     # content-type
	    $date,  # date
	    $path;  # path

	$h->{Date} = $date;
	$h->{Authorization} = _signature($keyId, $keySecret, $toSign);

	$r->proxyreq(1);
	$r->uri("http://s3.amazonaws.com$path");
	$r->filename("proxy:http://s3.amazonaws.com$path");
	$r->handler('proxy-server');

	return Apache2::Const::OK;
    }

    return Apache2::Const::DECLINED;
}

1;
